import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Define the vector field F(x, y, z) = (yz, xz, xy + exp(-x^2 - y^2 - z^2))
def vector_field(x, y, z):
"""Vector field F(x, y, z) = (yz, xz, xy + exp(-x^2 - y^2 - z^2))"""
F_x = y * z
F_y = x * z
F_z = x * y + np.exp(-(x**2) - y**2 - z**2)
return np.array([F_x, F_y, F_z])
# Calculate Gradient (for visualization purposes)
def divergence(x, y, z, h=1e-5):
"""Calculate the divergence of the vector field using finite differences."""
dFxdx = (vector_field(x + h, y, z)[0] - vector_field(x - h, y, z)[0]) / (2 * h)
dFydy = (vector_field(x, y + h, z)[1] - vector_field(x, y - h, z)[1]) / (2 * h)
dFzdz = (vector_field(x, y, z + h)[2] - vector_field(x, y, z - h)[2]) / (2 * h)
return dFxdx + dFydy + dFzdz
def curl(x, y, z, h=1e-5):
"""Calculate the curl of the vector field using finite differences."""
dFz_dy = (vector_field(x, y + h, z)[2] - vector_field(x, y - h, z)[2]) / (2 * h)
dFy_dz = (vector_field(x, y, z + h)[1] - vector_field(x, y, z - h)[1]) / (2 * h)
dFx_dz = (vector_field(x, y, z + h)[0] - vector_field(x, y, z - h)[0]) / (2 * h)
dFz_dx = (vector_field(x + h, y, z)[2] - vector_field(x - h, y, z)[2]) / (2 * h)
dFy_dx = (vector_field(x + h, y, z)[1] - vector_field(x - h, y, z)[1]) / (2 * h)
dFx_dy = (vector_field(x, y + h, z)[0] - vector_field(x, y - h, z)[0]) / (2 * h)
curl_x = dFz_dy - dFy_dz
curl_y = dFx_dz - dFz_dx
curl_z = dFy_dx - dFx_dy
return np.array([curl_x, curl_y, curl_z])
# Generate 3D grid points
x_vals = np.linspace(-2, 2, 20) # Adjust the range for better visualization
y_vals = np.linspace(-2, 2, 20)
z_vals = np.linspace(-2, 2, 20)
X, Y, Z = np.meshgrid(x_vals, y_vals, z_vals)
# Initialize arrays for vector field, divergence, and curl
vector_values = np.zeros((X.size, 3))
divergence_values = np.zeros(X.size)
curl_vectors = np.zeros((X.size, 3))
# Calculate field values
for i in range(X.size):
x, y, z = X.flatten()[i], Y.flatten()[i], Z.flatten()[i]
# Calculate Vector Field
vec = vector_field(x, y, z)
vector_values[i] = vec
# Calculate Divergence
div = divergence(x, y, z)
divergence_values[i] = div
# Calculate Curl
crl = curl(x, y, z)
curl_vectors[i] = crl
# Prepare Plotly figures
fig = make_subplots(
rows=1,
cols=3,
specs=[[{"type": "scatter3d"}, {"type": "scatter3d"}, {"type": "scatter3d"}]],
subplot_titles=["Vector Field", "Divergence", "Curl"],
)
# Vector Field Plot
fig.add_trace(
go.Cone(
x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
u=vector_values[:, 0],
v=vector_values[:, 1],
w=vector_values[:, 2],
sizemode="absolute",
sizeref=0.5,
colorscale="Blues",
),
row=1,
col=1,
)
# Divergence Field Plot
fig.add_trace(
go.Scatter3d(
x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
mode="markers",
marker=dict(
size=4,
color=divergence_values,
colorscale="Reds",
colorbar=dict(title="Divergence"),
),
),
row=1,
col=2,
)
# Curl Field Plot
fig.add_trace(
go.Cone(
x=X.flatten(),
y=Y.flatten(),
z=Z.flatten(),
u=curl_vectors[:, 0],
v=curl_vectors[:, 1],
w=curl_vectors[:, 2],
sizemode="absolute",
sizeref=0.5,
colorscale="Greens",
),
row=1,
col=3,
)
# Update Layout
fig.update_layout(
height=600,
width=1800,
title_text="3D Visualization of Vector Field, Divergence, and Curl",
showlegend=False,
)
fig.show()Nabla
In \(\mathbb{R}^3\) the nabla operator is defined as: \[ \nabla=\mathbf{e}_x \frac{\partial}{\partial x}+\mathbf{e}_y \frac{\partial}{\partial y}+\mathbf{e}_z \frac{\partial}{\partial z}=\left[\frac{\partial}{\partial x}, \frac{\partial}{\partial y}, \frac{\partial}{\partial z}\right] \] where \(\mathbf{e}_x\), \(\mathbf{e}_y\) and \(\mathbf{e}_z\) are the unit vectors in the \(x\), \(y\) and \(z\) directions respectively, i.e. standard basis.
Gradient, Divergence and Curl
The gradient of a scalar field \(f(x,y,z)\) is a vector field defined as: \[ \nabla f = \left[\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}, \frac{\partial f}{\partial z}\right] \]
The divergence of a vector field \(\mathbf{F}(x,y,z)\) is a scalar field defined as: \[ \nabla \cdot \mathbf{F} = \frac{\partial F_x}{\partial x} + \frac{\partial F_y}{\partial y} + \frac{\partial F_z}{\partial z} \]
The curl of a vector field \(\mathbf{F}(x,y,z)\) is a vector field defined as a determinant: \[ \nabla \times \mathbf{F} = \left[\frac{\partial}{\partial x}, \frac{\partial}{\partial y}, \frac{\partial}{\partial z}\right] \times \begin{vmatrix} \mathbf{e}_x & \mathbf{e}_y & \mathbf{e}_z \\ \frac{\partial}{\partial x} & \frac{\partial}{\partial y} & \frac{\partial}{\partial z} \\ F_x & F_y & F_z \end{vmatrix} \]
All these operators are linear, which are important properties for solving differential equations, that we know the linear combination of two solutions is also a solution.
Linear Properties of Nabla
The nabla operator has the following linear properties, such that for any scalar field \(f\) and \(g\) and any constant \(c\), for gradient: \[ \nabla(f+g)=\nabla f+\nabla g\\ \nabla(c f)=c \nabla f \]